#pragma once
#include <string.h>
#include <stdio.h>   
#include <stdlib.h>
#include "Eigen/Core"

using namespace std;

namespace REC3D
{
	struct Key
	{
		float x = 0.0f;
		float y = 0.0f;
		unsigned char r, g, b;
	};

	struct ImageInfo
	{
		int ID;
		int group_id = 0;
		bool valid;
		unsigned width = 0;
		unsigned height = 0;
		float fx = 0.0f;
		float fy = 0.0f;
		float u = 0.0f;
		float v = 0.0f;
		float k1 = 0.0f;
		float k2 = 0.0f;
		double cx = 0.0f;
		double cy = 0.0f;
		double cz = 0.0f;
		vector<float> R;
		vector<Key> keys;
		double gps_x = DBL_MAX;
		double gps_y = DBL_MAX;
		double gps_z = DBL_MAX;
	};
	typedef vector<ImageInfo> ImageInfos;

	struct KeyMatch
	{
		int keyIdx1 = -1;
		int keyIdx2 = -1;
	};

	struct ImagePairMatch
	{
		int image_id1 = -1;
		int image_id2 = -1;
		int model = 0;
		vector<double> M;
		vector<KeyMatch> keyMatches;
	};
	typedef vector<ImagePairMatch> ImagePairMatches;

	struct SparsePoints
	{
		vector<Eigen::Vector3f> Xs;
		vector<Eigen::Vector3f> Xnormals;
		vector<Eigen::Vector3f> Colors;
		vector<unsigned int> views;
		vector<unsigned int> tracks;
	};

	struct SfMParams
	{
		int k_cover = 2048;
		int n_OMST = 100;
		int min_P3P_matches = 24;
		int min_P3P_inliers = 9;
		int min_vis_views = 2;
		int ra_conf = 0;
		float min_tri_angle = 1.5;
		float rigister_ratio = 0.3;
		int points_level = 0; // 0:all tracks, n:select n tracks
		string GCPFile = "";
		string bundlerFile = "";
		string cameraFile = "";
		float gps_err = 10;
		bool sfm_report = 0;
	};
}

int SfMSolver(REC3D::ImageInfos& imageInfos, REC3D::ImagePairMatches& imagePairMatches, REC3D::SparsePoints& sparsePoints, string SfMDir,
	          REC3D::SfMParams& sfmParams);